From: Keir Fraser Date: Tue, 21 Oct 2008 08:47:33 +0000 (+0100) Subject: x86: Adapt 32b guest os to 64b hypervisor platform_hypercall compatibility X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14066^2~13 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=bd021534ed633e2d1921b4811dc80083a1a04def;p=xen.git x86: Adapt 32b guest os to 64b hypervisor platform_hypercall compatibility Changeset 18552 (19b0a4f91712) move px transfer logic from platform_hypercall.c to a common file to support both x86 and ia64. However, it involves 32b guest os to 64b hypervisor (x86) compatible issue. This patch fix the compatible issue, and make set_px_pminfo() re-used by ia64 and x86 (32b guest os to 64b hypervisor, and 64b guest os to 64b hypervisor). Signed-off-by: Liu Jinsong --- diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index 99060a0d56..28ab32678b 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -53,15 +53,6 @@ static long cpu_frequency_change_helper(void *data) return cpu_frequency_change(this_cpu(freq)); } -int xenpf_copy_px_states(struct processor_performance *pxpt, - struct xen_processor_performance *dom0_px_info) -{ - if (!pxpt || !dom0_px_info) - return -EINVAL; - return copy_from_compat(pxpt->states, dom0_px_info->states, - dom0_px_info->state_count); -} - ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) { ret_t ret = 0; @@ -372,12 +363,13 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) switch ( op->u.set_pminfo.type ) { case XEN_PM_PX: - { - - ret = set_px_pminfo(op->u.set_pminfo.id, - &op->u.set_pminfo.perf); + if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) ) + { + ret = -ENOSYS; + break; + } + ret = set_px_pminfo(op->u.set_pminfo.id, &op->u.set_pminfo.perf); break; - } case XEN_PM_CX: if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_CX) ) diff --git a/xen/arch/x86/x86_64/Makefile b/xen/arch/x86/x86_64/Makefile index 268494745c..959eaef889 100644 --- a/xen/arch/x86/x86_64/Makefile +++ b/xen/arch/x86/x86_64/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_COMPAT) += domain.o obj-$(CONFIG_COMPAT) += physdev.o obj-$(CONFIG_COMPAT) += platform_hypercall.o obj-$(CONFIG_COMPAT) += cpu_idle.o +obj-$(CONFIG_COMPAT) += cpufreq.o ifeq ($(CONFIG_COMPAT),y) # extra dependencies @@ -24,4 +25,5 @@ platform_hypercall.o: ../platform_hypercall.c sysctl.o: ../sysctl.c traps.o: compat/traps.c cpu_idle.o: ../acpi/cpu_idle.c +cpufreq.o: ../../../drivers/cpufreq/cpufreq.c endif diff --git a/xen/arch/x86/x86_64/cpu_idle.c b/xen/arch/x86/x86_64/cpu_idle.c index 6718f30a54..c26248e97b 100644 --- a/xen/arch/x86/x86_64/cpu_idle.c +++ b/xen/arch/x86/x86_64/cpu_idle.c @@ -44,7 +44,7 @@ DEFINE_XEN_GUEST_HANDLE(compat_processor_cx_t); xlat_page_current = xlat_page_start; \ } while (0) -static void *xlat_malloc(unsigned long *xlat_page_current, size_t size) +void *xlat_malloc(unsigned long *xlat_page_current, size_t size) { void *ret; diff --git a/xen/arch/x86/x86_64/cpufreq.c b/xen/arch/x86/x86_64/cpufreq.c new file mode 100644 index 0000000000..1931eecfaf --- /dev/null +++ b/xen/arch/x86/x86_64/cpufreq.c @@ -0,0 +1,91 @@ +/****************************************************************************** + * cpufreq.c -- adapt 32b compat guest to 64b hypervisor. + * + * Copyright (C) 2008, Liu Jinsong + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include +#include +#include + +DEFINE_XEN_GUEST_HANDLE(compat_processor_px_t); + +#define xlat_page_start ((unsigned long)COMPAT_ARG_XLAT_VIRT_BASE) + +#define xlat_malloc_init(xlat_page_current) do { \ + xlat_page_current = xlat_page_start; \ +} while (0) + +extern void *xlat_malloc(unsigned long *xlat_page_current, size_t size); + +#define xlat_malloc_array(_p, _t, _c) ((_t *) xlat_malloc(&_p, sizeof(_t) * _c)) + +extern int +set_px_pminfo(uint32_t cpu, struct xen_processor_performance *perf); + +int +compat_set_px_pminfo(uint32_t cpu, struct compat_processor_performance *perf) +{ + struct xen_processor_performance *xen_perf; + unsigned long xlat_page_current; + + xlat_malloc_init(xlat_page_current); + + xen_perf = xlat_malloc_array(xlat_page_current, + struct xen_processor_performance, 1); + if ( unlikely(xen_perf == NULL) ) + return -EFAULT; + +#define XLAT_processor_performance_HNDL_states(_d_, _s_) do { \ + xen_processor_px_t *xen_states = NULL; \ +\ + if ( likely((_s_)->state_count > 0) ) \ + { \ + XEN_GUEST_HANDLE(compat_processor_px_t) states; \ + compat_processor_px_t state; \ + int i; \ +\ + xen_states = xlat_malloc_array(xlat_page_current, \ + xen_processor_px_t, (_s_)->state_count); \ + if ( unlikely(xen_states == NULL) ) \ + return -EFAULT; \ +\ + if ( unlikely(!compat_handle_okay((_s_)->states, \ + (_s_)->state_count)) ) \ + return -EFAULT; \ + guest_from_compat_handle(states, (_s_)->states); \ +\ + for ( i = 0; i < _s_->state_count; i++ ) \ + { \ + if ( unlikely(copy_from_guest_offset(&state, states, i, 1)) ) \ + return -EFAULT; \ + XLAT_processor_px(&xen_states[i], &state); \ + } \ + } \ +\ + set_xen_guest_handle((_d_)->states, xen_states); \ +} while (0) + XLAT_processor_performance(xen_perf, perf); +#undef XLAT_processor_performance_HNDL_states + + return set_px_pminfo(cpu, xen_perf); +} diff --git a/xen/arch/x86/x86_64/platform_hypercall.c b/xen/arch/x86/x86_64/platform_hypercall.c index 02364c4535..2002900d61 100644 --- a/xen/arch/x86/x86_64/platform_hypercall.c +++ b/xen/arch/x86/x86_64/platform_hypercall.c @@ -11,14 +11,14 @@ DEFINE_XEN_GUEST_HANDLE(compat_platform_op_t); #define xen_platform_op_t compat_platform_op_t #define do_platform_op(x) compat_platform_op(_##x) -#define xenpf_copy_px_states compat_xenpf_copy_px_states - #define xen_processor_px compat_processor_px #define xen_processor_px_t compat_processor_px_t #define xen_processor_performance compat_processor_performance #define xen_processor_performance_t compat_processor_performance_t #define xenpf_set_processor_pminfo compat_pf_set_processor_pminfo +#define set_px_pminfo compat_set_px_pminfo + #define xen_processor_power compat_processor_power #define xen_processor_power_t compat_processor_power_t #define set_cx_pminfo compat_set_cx_pminfo diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c index add3f2daf9..08d5576f7a 100644 --- a/xen/drivers/cpufreq/cpufreq.c +++ b/xen/drivers/cpufreq/cpufreq.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -217,14 +218,8 @@ int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *dom0_px_in struct processor_pminfo *pmpt; struct processor_performance *pxpt; - if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) ) - { - ret = -ENOSYS; - goto out; - } - cpuid = get_cpu_id(acpi_id); - if ( cpuid < 0 ) + if ( cpuid < 0 || !dom0_px_info) { ret = -EINVAL; goto out; @@ -265,12 +260,8 @@ int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *dom0_px_in ret = -ENOMEM; goto out; } - if ( xenpf_copy_px_states(pxpt, dom0_px_info) ) - { - xfree(pxpt->states); - ret = -EFAULT; - goto out; - } + copy_from_guest(pxpt->states, dom0_px_info->states, + dom0_px_info->state_count); pxpt->state_count = dom0_px_info->state_count; print_PSS(pxpt->states,pxpt->state_count); } diff --git a/xen/include/acpi/cpufreq/processor_perf.h b/xen/include/acpi/cpufreq/processor_perf.h index 7821aeffb1..401e101ac7 100644 --- a/xen/include/acpi/cpufreq/processor_perf.h +++ b/xen/include/acpi/cpufreq/processor_perf.h @@ -60,8 +60,5 @@ struct pm_px { extern struct pm_px *cpufreq_statistic_data[NR_CPUS]; -int xenpf_copy_px_states(struct processor_performance *pxpt, - struct xen_processor_performance *dom0_px_info); - int cpufreq_cpu_init(unsigned int cpuid); #endif /* __XEN_PROCESSOR_PM_H__ */ diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst index 6f0b662b00..c38dd39a9f 100644 --- a/xen/include/xlat.lst +++ b/xen/include/xlat.lst @@ -55,3 +55,7 @@ ! processor_cx platform.h ! processor_flags platform.h ! processor_power platform.h +! pct_register platform.h +! processor_px platform.h +! psd_package platform.h +! processor_performance platform.h